package com.didichuxing.doraemondemo

import android.Manifest
import android.annotation.SuppressLint
import android.app.ProgressDialog
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.location.Location
import android.location.LocationListener
import android.location.LocationManager
import android.net.Uri
import android.os.*
import android.text.format.Formatter
import android.util.Log
import android.view.View
import android.widget.ImageView
import android.widget.Toast
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import coil.imageLoader
import coil.request.CachePolicy
import coil.transform.CircleCropTransformation
import com.amap.api.location.AMapLocationListener
import com.blankj.utilcode.util.*
import com.bumptech.glide.Glide
import com.bumptech.glide.RequestBuilder
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.resource.bitmap.CircleCrop
import com.didichuxing.doraemondemo.amap.AMapRouterFragment
import com.didichuxing.doraemondemo.comm.CommLauncher
import com.didichuxing.doraemondemo.databinding.ActivityMainBinding
import com.didichuxing.doraemondemo.mc.MCActivity
import com.didichuxing.doraemondemo.retrofit.GithubService
import com.didichuxing.doraemonkit.DoKit
import com.facebook.drawee.backends.pipeline.Fresco
import com.lzy.okgo.OkGo
import com.lzy.okgo.callback.StringCallback
import com.lzy.okgo.model.Response
import com.nostra13.universalimageloader.core.ImageLoader
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration
import com.squareup.picasso.MemoryPolicy
import com.squareup.picasso.Picasso
import com.squareup.picasso.RequestCreator
import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.*
import okhttp3.*
import org.json.JSONObject
import pub.devrel.easypermissions.EasyPermissions
import pub.devrel.easypermissions.PermissionRequest
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.converter.scalars.ScalarsConverterFactory
import java.io.*
import java.net.*
import kotlin.coroutines.resume

/**
 * @author jintai
 */
class MainDebugActivityOkhttpV3 : BaseActivity(), View.OnClickListener, CoroutineScope by MainScope() {

    private var okHttpClient: OkHttpClient? = null
    private var mLocationManager: LocationManager? = null
    private val UPDATE_UI = 100
    private lateinit var mAdapter: MainAdapter

    private val retrofit = Retrofit.Builder()
        .baseUrl("https://api.github.com/")
        .addConverterFactory(ScalarsConverterFactory.create())
        .addConverterFactory(GsonConverterFactory.create())
        .build()

    /**
     * github 接口
     */
    private var githubService: GithubService? = null

    private var _binding: ActivityMainBinding? = null

    @SuppressLint("HandlerLeak")
    private val mHandler: Handler = object : Handler() {
        override fun handleMessage(msg: Message) {
            super.handleMessage(msg)
            when (msg.what) {
                100 -> _binding?.ivPicasso?.setImageBitmap(msg.obj as Bitmap)
                else -> {
                }
            }
        }
    }

    val datas = mutableListOf(
        "显示/隐藏Dokit入口",
        "显示工具面板",
        "弹框测试",
        "系统反射测试",
        "获取已安装的app",
        "截屏",
        "跳转其他Activity",
        "一机多控",
        "NormalWebView",
        "X5WebView",
        "模拟内存泄漏",
        "函数调用耗时(TAG:MethodCostUtil)",
        "获取位置信息(系统)",
        "高德路径规划",
        "OkHttp Mock",
        "HttpURLConnection Mock",
        "Retrofit Mock",
        "模拟Crash",
        "创建数据库",
        "上传文件",
        "下载文件"
    )


    suspend fun sleep() = suspendCancellableCoroutine<String> {
        Thread.sleep(5000)
        it.resume("sleep 1000ms")
    }

    fun sleep2(): String {
        Thread.sleep(5000)
        return "sleep 1000ms"
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        _binding = ActivityMainBinding.inflate(layoutInflater).also {
            setContentView(it.root)
            mAdapter = MainAdapter(R.layout.item_main_rv, datas)
            it.initView(this)
        }
        mAdapter.setOnItemClickListener { _, _, position ->
            when (datas[position]) {
                "弹框测试" -> {
//                    val bundle = Bundle()
//                    bundle.putString("text", "测试同步异常")
//                    DoKit.launchFloating<McDialogDoKitView>(bundle = bundle)

                    lifecycleScope.launch {
                        delay(15000)
                        Log.i(TAG, "===inner===")
                    }
                    Log.i(TAG, "===out===")

                }
                "系统反射测试" -> {
                    try {
                        val activityClass = Class.forName("dalvik.system.VMRuntime")
                        val field = activityClass.getDeclaredMethod("setHiddenApiExemptions", Array<String>::class.java)
                        field.isAccessible = true
                        Toast.makeText(this, "call success!!", Toast.LENGTH_SHORT).show()
                    } catch (e: Throwable) {
                        Log.e(TAG, "error:", e)
                        Toast.makeText(this, "error: $e", Toast.LENGTH_SHORT).show()
                    }
                }
                "显示/隐藏Dokit入口" -> {
                    if (DoKit.isMainIconShow) {
                        DoKit.hide()
                    } else {
                        DoKit.show()
                    }

                }
                "显示工具面板" -> {
                    DoKit.showToolPanel()
                }
                "获取已安装的app" -> {
                    packageManager.getInstalledApplications(
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) PackageManager.MATCH_UNINSTALLED_PACKAGES
                        else PackageManager.GET_UNINSTALLED_PACKAGES
                    )
                    packageManager.getInstalledApplications(PackageManager.MATCH_UNINSTALLED_PACKAGES)
                }
                "截屏" -> {
//                    lifecycleScope.launch {
//
//                        DoKit.launchFloating(BorderDoKitView::class.java)
//                        val borderDoKitView =
//                            DoKit.getDoKitView(
//                                this@MainDebugActivityOkhttpV3,
//                                BorderDoKitView::class.java
//                            ) as BorderDoKitView
//                        borderDoKitView.showBorder(view)
//                        withContext(Dispatchers.IO) {
//                            delay(200)
//                            val bitmap = ScreenUtils.screenShot(this@MainDebugActivityOkhttpV3)
//                            val output = File(getCrashCacheDir(), "test.png")
//                            DoKitImageUtil.bitmap2File(bitmap, 100, output)
//                        }
//
//                    }

                }
                "跳转其他Activity" -> {
                    startActivity(Intent(this, SecondActivity::class.java))
                }
                "一机多控" -> {
                    startActivity(Intent(this, MCActivity::class.java))
                }
                "NormalWebView" -> {
                    startActivity(Intent(this, WebViewNormalActivity::class.java))
                }
                "X5WebView" -> {
                    startActivity(Intent(this, WebViewX5Activity::class.java))
                }

                "模拟内存泄漏" -> {
                    startActivity(Intent(this, LeakActivity::class.java))
                }

                "函数调用耗时(TAG:MethodCostUtil)" -> {
                    test1()
                }
                "获取位置信息(系统)" -> {
                    startNormaLocation()
                }
                "高德路径规划" -> {
                    CommLauncher.startActivity(AMapRouterFragment::class.java, this)
                }
                "OkHttp Mock" -> {
                    val jsonObject = JSONObject()
                    jsonObject.put("c", "cc")
                    jsonObject.put("d", "dd")
                    OkGo.post<String>("https://wanandroid.com/user_article/list/0/json?b=bb&a=aa")
                        .upJson(jsonObject)
                        .execute(object : StringCallback() {
                            override fun onSuccess(response: Response<String>?) {
                                response?.let {
                                    Log.i(TAG, "okhttp====onSuccess===>" + it.body())
                                }
                            }

                        })


//                    OkGo.post<String>("https://wanandroid.com/user_article/list/0/json?b=bb&a=aa")
//                        .params("c", "cc")
//                        .params("d", "dd")
//                        .execute()
//                    OkGo.get<String>("https://wanandroid.com/user_article/list/0/json?a=aa&b=bb")
//                        //.upJson(json.toString())
//                        .execute(object : StringCallback() {
//                            override fun onSuccess(response: Response<String>?) {
//                                response?.let {
//                                    Log.i(
//                                        MainDebugActivityOkhttpV3.TAG,
//                                        "okhttp====onSuccess===>" + it.body()
//                                    )
//                                }
//                            }
//
//                            override fun onError(response: Response<String>?) {
//                                response?.let {
//                                    Log.i(
//                                        MainDebugActivityOkhttpV3.TAG,
//                                        "okhttp====onError===>" + it.message()
//                                    )
//                                }
//                            }
//
//                        })
                }
                "HttpURLConnection Mock" -> {
                    requestByGet("https://wanandroid.com/user_article/list/0/json")
                }
                "Retrofit Mock" -> {
                    lifecycleScope.launch {
                        val result = githubService?.githubUserInfo("jtsky")
                        Log.i(TAG, "result===>${result}")
                    }

                }
                "模拟Crash" -> {
                    checkNotNull(testCrash())
                }
                "创建数据库" -> {
                    val dbHelper = MyDatabaseHelper(this, "BookStore.db", null, 1)
                    dbHelper.writableDatabase
                    dbHelper.close()
                }
                "上传文件" -> {
                    requestByFile(true)
                }
                "下载文件" -> {
                    requestByFile(false)
                }
                else -> {
                }
            }
        }

        okHttpClient = OkHttpClient().newBuilder().build()
        //获取定位服务
        mLocationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
        //高德定位服务
        EasyPermissions.requestPermissions(
            PermissionRequest.Builder(
                this, 200,
                Manifest.permission.ACCESS_FINE_LOCATION,
                Manifest.permission.ACCESS_COARSE_LOCATION,
                Manifest.permission.READ_EXTERNAL_STORAGE,
                Manifest.permission.WRITE_EXTERNAL_STORAGE
            ).build()
        )
        //初始化
        val config = ImageLoaderConfiguration.Builder(this)
            .build()
        ImageLoader.getInstance().init(config)

        githubService = retrofit.create(GithubService::class.java)
    }

    private fun ActivityMainBinding.initView(context: Context) {
        tvEnv.text = "${getString(R.string.app_build_types)}:Debug"
        rv.layoutManager = LinearLayoutManager(context)
        rv.adapter = mAdapter
        btnLoadImg.setOnClickListener(this@MainDebugActivityOkhttpV3)
    }

    private fun test1() {
        try {
            Thread.sleep(1000)
        } catch (e: InterruptedException) {
            e.printStackTrace()
        }
        test2()
    }

    private fun test2() {
        try {
            Thread.sleep(200)
        } catch (e: InterruptedException) {
            e.printStackTrace()
        }
        test3()
    }

    private fun test3() {
        try {
            Thread.sleep(200)
        } catch (e: InterruptedException) {
            e.printStackTrace()
        }
        test4()
    }

    private fun test4() {
        try {
            Thread.sleep(200)
        } catch (e: InterruptedException) {
            e.printStackTrace()
        }
    }

    private val mLocationListener: LocationListener = object : LocationListener {
        override fun onLocationChanged(location: Location) {
            val string = "lat====>" + location.latitude + "  lng====>" + location.longitude
            Log.i(TAG, "系统定位====>$string")
        }

        override fun onProviderDisabled(arg0: String) {}
        override fun onProviderEnabled(arg0: String) {}
        override fun onStatusChanged(arg0: String, arg1: Int, arg2: Bundle) {}
    }

    /**
     * 启动普通定位
     */
    @SuppressLint("MissingPermission")
    private fun startNormaLocation() {
        mLocationManager!!.requestLocationUpdates(
            LocationManager.NETWORK_PROVIDER,
            0,
            0f,
            mLocationListener
        )
    }

    /**
     * 启动高德定位服务
     */
    private var mapLocationListener = AMapLocationListener { aMapLocation ->
        val errorCode = aMapLocation.errorCode
        val errorInfo = aMapLocation.errorInfo
        Log.i(
            TAG,
            "高德定位===lat==>" + aMapLocation.latitude + "   lng==>" + aMapLocation.longitude + "  errorCode===>" + errorCode + "   errorInfo===>" + errorInfo
        )
    }

    @SuppressLint("MissingPermission")
    override fun onClick(v: View) {
        when (v.id) {

            R.id.btn_load_img -> {
                //Glide 加载
                val picassoImgUrl =
                    "https://gimg2.baidu.com/image_search/src=http%3A%2F%2F2c.zol-img.com.cn%2Fproduct%2F124_500x2000%2F748%2FceZOdKgDAFsq2.jpg&refer=http%3A%2F%2F2c.zol-img.com.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1621652979&t=850e537c70eaa7753e892bc8b4d05f57"
                val glideImageUrl =
                    "https://gimg2.baidu.com/image_search/src=http%3A%2F%2F1812.img.pp.sohu.com.cn%2Fimages%2Fblog%2F2009%2F11%2F18%2F18%2F8%2F125b6560a6ag214.jpg&refer=http%3A%2F%2F1812.img.pp.sohu.com.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1621652979&t=76d35d35d9c510f1c24a422e9e02fd46"
                val frescoImageUrl =
                    "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fyouimg1.c-ctrip.com%2Ftarget%2Ftg%2F035%2F063%2F726%2F3ea4031f045945e1843ae5156749d64c.jpg&refer=http%3A%2F%2Fyouimg1.c-ctrip.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1621652979&t=7150aaa2071d512cf2f6b556e126dd66"
                val imageLoaderImageUrl =
                    "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fyouimg1.c-ctrip.com%2Ftarget%2Ftg%2F004%2F531%2F381%2F4339f96900344574a0c8ca272a7b8f27.jpg&refer=http%3A%2F%2Fyouimg1.c-ctrip.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1621652979&t=b7e83ecc987c64cc31079469d292eb56"
                val coilImageUrl =
                    "https://cdn.nlark.com/yuque/0/2020/png/252337/1587091196083-assets/web-upload/62122ab5-986b-4662-be88-d3007a5e31c5.png"
                Picasso.get().load(picassoImgUrl)
                    .memoryPolicy(MemoryPolicy.NO_CACHE)
                    .placeholder(R.mipmap.cat)
                    .error(R.mipmap.cat)
                    .intoOrCancel(_binding?.ivPicasso)
                Glide.with(this@MainDebugActivityOkhttpV3)
                    .asBitmap()
                    .load(glideImageUrl)
                    .placeholder(R.mipmap.cat)
                    .error(R.mipmap.cat)
                    .diskCacheStrategy(DiskCacheStrategy.NONE)
                    .skipMemoryCache(true)
                    .transform(CircleCrop())
                    .intoOrCancel(_binding?.ivGlide)
                //coil
                _binding?.ivCoil?.apply {
                    val request = coil.request.ImageRequest.Builder(this.context)
                        .memoryCachePolicy(CachePolicy.DISABLED)
                        .transformations(CircleCropTransformation())
                        .diskCachePolicy(CachePolicy.DISABLED)
                        .data(coilImageUrl)
                        .target(this)
                        .build()
                    imageLoader.enqueue(request)
                }
                //imageLoader
                val imageLoader = ImageLoader.getInstance()
                imageLoader.displayImageOrNot(imageLoaderImageUrl, _binding?.ivImageloader)
                //fresco
                _binding?.ivFresco?.setImageURI(Uri.parse(frescoImageUrl))
                val imagePipeline = Fresco.getImagePipeline()
                // combines above two lines
                imagePipeline.clearCaches()
            }

            else -> {
            }
        }
    }

    private fun testCrash(): String? {
        return null
    }

    private fun requestByGet(path: String) {
        ThreadUtils.executeByIo(object : ThreadUtils.SimpleTask<String?>() {
            @Throws(Throwable::class)
            override fun doInBackground(): String {
                try {
                    val url = URL(path.trim())
                    //打开连接
                    val urlConnection = url.openConnection() as HttpURLConnection
                    //urlConnection.setRequestProperty("token", "10051:abc");
                    //urlConnection.setRequestProperty("Content-type", "application/json");
                    //int log = urlConnection.getResponseCode();
                    //得到输入流
                    val `is` = urlConnection.inputStream
                    return ConvertUtils.inputStream2String(`is`, "utf-8")
                } catch (e: IOException) {
                    e.printStackTrace()
                }
                return "error"
            }


            override fun onSuccess(result: String?) {
                Log.i(TAG, "httpUrlConnection====response===>===>$result")
            }
        })
    }


    /**
     * 模拟上传或下载文件
     *
     * @param upload true上传 false下载
     */
    private fun requestByFile(upload: Boolean) {
        val dialog = ProgressDialog.show(this, null, null)
        dialog.setCancelable(true)
        var request: Request? = null
        if (upload) {
            try {
                //模拟一个1M的文件用来上传
                val length = 1L * 1024 * 1024
                val temp = File(filesDir, "test.tmp")
                if (!temp.exists() || temp.length() != length) {
                    val accessFile = RandomAccessFile(temp, "rwd")
                    accessFile.setLength(length)
                    temp.createNewFile()
                }
                request = Request.Builder()
                    .post(RequestBody.create(MediaType.parse(temp.name), temp))
                    .url("http://wallpaper.apc.360.cn/index.php?c=WallPaper&a=getAppsByOrder&order=create_time&start=0&count=1&from=360chrome")
                    .build()
            } catch (e: IOException) {
                e.printStackTrace()
            }
        } else {
            //下载一个2M的文件
            request = Request.Builder()
                .get()
                .url("http://cdn1.lbesec.com/products/history/20131220/privacyspace_rel_2.2.1617.apk")
                .build()
        }
        val call = okHttpClient!!.newCall(request!!)
        val startTime = SystemClock.uptimeMillis()
        call.enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                dialog.cancel()
                onHttpFailure(e)
            }

            @Throws(IOException::class)
            override fun onResponse(call: Call, response: okhttp3.Response) {
                if (!response.isSuccessful) {
                    onFailure(call, IOException(response.message()))
                    return
                }
                val body = response.body()
                if (!upload) {
                    inputStream2File(body!!.byteStream(), File(filesDir, "test.apk"))
                }
                dialog.cancel()
                val requestLength = if (upload) call.request().body()!!.contentLength() else 0
                val responseLength = if (body!!.contentLength() < 0) 0 else body.contentLength()
                val endTime = SystemClock.uptimeMillis() - startTime
                val speed = (if (upload) requestLength else responseLength) / endTime * 1000
                val message = String.format(
                    "请求大小：%s，响应大小：%s，耗时：%dms，均速：%s/s",
                    Formatter.formatFileSize(applicationContext, requestLength),
                    Formatter.formatFileSize(applicationContext, responseLength),
                    endTime,
                    Formatter.formatFileSize(applicationContext, speed)
                )
                runOnUiThread {
                    Log.d("onResponse", message)
                    Toast.makeText(this@MainDebugActivityOkhttpV3, message, Toast.LENGTH_LONG)
                        .show()
                }
            }
        })
    }

    private fun onHttpFailure(e: IOException) {
        e.printStackTrace()
        runOnUiThread {
            if (e is UnknownHostException) {
                Toast.makeText(this@MainDebugActivityOkhttpV3, "网络异常", Toast.LENGTH_SHORT).show()
            } else if (e is SocketTimeoutException) {
                Toast.makeText(this@MainDebugActivityOkhttpV3, "请求超时", Toast.LENGTH_SHORT).show()
            } else {
                Toast.makeText(this@MainDebugActivityOkhttpV3, e.message, Toast.LENGTH_LONG)
                    .show()
            }
        }
    }

    private fun inputStream2File(`is`: InputStream, saveFile: File) {
        var len: Int
        val buf = ByteArray(2048)
        val fos = FileOutputStream(saveFile)
        `is`.use { input ->
            fos.use { output ->
                while (input.read(buf).also { len = it } != -1) {
                    output.write(buf, 0, len)
                }
                output.flush()
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        okHttpClient!!.dispatcher().cancelAll()
        mLocationManager!!.removeUpdates(mLocationListener)
    }

    private fun requestImage(urlStr: String) {
        try {
            //
            val url = URL(urlStr)
            // http    https
            // ftp
            val urlConnection = url.openConnection() as HttpURLConnection
            //http get post
            urlConnection.requestMethod = "GET"
            urlConnection.connectTimeout = 5000
            urlConnection.readTimeout = 5000
            val responseCode = urlConnection.responseCode
            if (responseCode == 200) {
                val bitmap = BitmapFactory.decodeStream(urlConnection.inputStream)
                //更新 ui
                mHandler.sendMessage(mHandler.obtainMessage(UPDATE_UI, bitmap))
            }
        } catch (e: MalformedURLException) {
            e.printStackTrace()
        } catch (e: IOException) {
            e.printStackTrace()
        }
    }

    private fun RequestCreator.intoOrCancel(target: ImageView?) {
        target?.also { into(it) }
    }

    private fun RequestBuilder<*>.intoOrCancel(target: ImageView?) {
        target?.also { into(it) }
    }

    private fun ImageLoader.displayImageOrNot(url: String, target: ImageView?) {
        target?.also { displayImage(url, it) }
    }

    companion object {
        const val TAG = "MainDebugActivity"
    }
}
